import Knex from "~/src/library/mysql";
import moment from "moment";
import _ from "lodash";
import MProject from "~/src/model/project/project";
import MSystem from "~/src/model/parse/system";
import Logger from "~/src/library/logger";
import MCityDistribution from "~/src/model/parse/city_distribution";
import DATE_FORMAT from "~/src/constants/date_format";

const BASE_TABLE_NAME = "t_r_system_device";
const TABLE_COLUMN = [
  `id`,
  `project_id`,
  `device_vendor`,
  `device_model`,
  `total_count`,
  `count_at_month`,
  `city_distribute_id`,
  `create_time`,
  `update_time`,
];

/**
 * 获取表名
 * @param {number} projectId 项目id
 * @param {number} createTimeAt 创建时间, 时间戳
 * @return {String}
 */
function getTableName() {
  return BASE_TABLE_NAME;
}

async function summarySystemDevice(visitAt) {
  let visitAtMonth = moment.unix(visitAt).format(DATE_FORMAT.DATABASE_BY_MONTH);
  const projectList = await MProject.getList();
  for (let rawProject of projectList) {
    const projectId = _.get(rawProject, "id", "");
    const projectName = _.get(rawProject, "project_name", "");
    const systemTableName = MSystem.getTableName(projectId);
    Logger.info(`开始处理项目${projectId}(${projectName})的数据`);
    Logger.info(`[${projectId}(${projectName})] 统计月份:${visitAtMonth}`);
    const sumRes = await Knex.count("* as total_count")
      .select([
        `device_vendor`,
        `device_model`,
        `visit_at_month`,
        `country`,
        `province`,
        `city`,
      ])
      .from(systemTableName)
      .where("visit_at_month", "=", visitAtMonth)
      .groupBy("device_vendor")
      .groupBy("device_model")
      .groupBy("country")
      .groupBy("province")
      .groupBy("city")
      .catch(err => {
        Logger.error(err);
        return [];
      });
    if (sumRes.length === 0) {
      continue;
    }

    let deviceVersionRecord = {};
    for (let countItem of sumRes) {
      const {
        device_model: deviceModel,
        device_vendor: deviceVendor,
        country,
        province,
        city,
        total_count: totalCount,
        visit_at_month: countAtMonth,
      } = countItem;
      let distribution = {};
      let distributionPath = [country, province, city];
      _.set(distribution, distributionPath, totalCount);
      let deviceVersionKey = deviceModel + deviceVendor;
      if (_.has(deviceVersionRecord, deviceVersionKey)) {
        // 若是已经有，更新count/distribution
        let oldCount = _.get(
          deviceVersionRecord,
          [deviceVersionKey, "totalCount"],
          0
        );
        let newCount = oldCount + totalCount;
        let oldDistribution = _.get(
          deviceVersionRecord,
          [deviceVersionKey, "distribution"],
          {}
        );
        let cityDistribute = MCityDistribution.mergeDistributionData(
          distribution,
          oldDistribution,
          (newCityRecord, oldCityRecord) => {
            return newCityRecord + oldCityRecord;
          }
        );
        _.set(deviceVersionRecord, [deviceVersionKey, "totalCount"], newCount);
        _.set(
          deviceVersionRecord,
          [deviceVersionKey, "distribution"],
          cityDistribute
        );
      } else {
        _.set(deviceVersionRecord, [deviceVersionKey], {
          totalCount: totalCount,
          deviceVendor: deviceVendor,
          deviceModel: deviceModel,
          countAtMonth: countAtMonth,
          distribution: distribution,
        });
      }
    }

    let totalCount = 0;
    for (let item of Object.keys(deviceVersionRecord)) {
      if (item) {
        totalCount = totalCount + 1;
      }
      let recordInfo = deviceVersionRecord[item];
      await replaceAndAutoIncreaseDeviceRecord(
        projectId,
        recordInfo,
        recordInfo["distribution"]
      );
    }
    Logger.info(
      `项目${projectId}(${projectName})处理完毕, 共处理${totalCount}条数据`
    );
  }
}


/**
 * 自动创建&更新, 并增加total_count的值
 * @param {number} projectId
 * @param {number} totalCount
 * @param {number} countAtMonth
 * @param {string} countType
 * @param {object} cityDistribute
 * @return {boolean}
 */
async function replaceAndAutoIncreaseDeviceRecord(
  projectId,
  recordInfo,
  totalCount,
  countAt,
  cityDistribute,
  appVersion
) {
  const {
    deviceType, // 设备类型
    OS, // 操作系统
    OSVersion, // 操作系统版本
    screenHeight, // 屏幕高
    screenWidth, // 屏幕宽
    language, // 当前使用的语言-国家
    netWork, // 联网类型
    orientation, // 横竖屏
    browser, // 浏览器信息
    browserVersion, // 浏览器信息
    browserEngine, // 浏览器信息
    fingerprint, // 浏览器指纹
    userAgent,
  } = recordInfo;
  let tableName = getTableName();
  let updateAt = moment().unix();
  let countAtMonth = moment
    .unix(countAt)
    .format(DATE_FORMAT.DATABASE_BY_UNIT["month"]);
  let data = {
    project_id: projectId,
    deviceType: deviceType, // 设备类型
    OS: OS, // 操作系统
    OSVersion: OSVersion, // 操作系统版本
    screenHeight: screenHeight, // 屏幕高
    screenWidth: screenWidth, // 屏幕宽
    language: language, // 当前使用的语言-国家
    netWork: netWork, // 联网类型
    orientation: orientation, // 横竖屏
    browser, // 浏览器信息
    browserVersion, // 浏览器信息
    browserEngine, // 浏览器信息
    fingerprint: fingerprint, // 浏览器指纹
    userAgent: userAgent,
    appVersion: appVersion,
    count_at_month: countAtMonth,
    total_count: totalCount,
    update_time: updateAt,
  };

  // 首先插入城市分布数据
  let cityDistributeId = await MCityDistribution.insertCityDistributionRecord(
    JSON.stringify(cityDistribute),
    projectId,
    updateAt
  );
  if (cityDistributeId === 0) {
    // 城市分布数据插入失败
    return false;
  }

  data["create_time"] = updateAt;
  let insertResult = await Knex.insert(data, ["id"])
    .into(tableName)
    .catch(e => {
      return [];
    });
  return _.get(insertResult, [0], 0);
}

/**
 * 获取记录
 */
async function getRecord(projectId, countAtMonth) {
  let tableName = getTableName();
  console.log(countAtMonth,projectId)
  let recordList = await Knex
    .from(tableName)
    .where("project_id", "=", projectId)
    .andWhere("count_at_month", "=", countAtMonth)
    .catch(() => {
      return [];
    });
  return recordList;
}

export default {
  replaceAndAutoIncreaseDeviceRecord,
  getRecord,
  summarySystemDevice,
};
